package com.question.dicegame;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.text.Position;

public class DiceGameBoard extends JPanel implements Runnable {

	// 프레임의 출력 간격을 정의하는 변수 (초당 40frame)
	public static int DELAY = 500;
	public static int DELAY2 = 250;

	// 게임 객체들이 사용할 이미지
	private Image[] headImage;
	private Image map;
	private Image[] dice;
	private Image itemImage;
	// int[] : 셀위치 (x,y)
	private int[][] player;
	private Font font;
	int number = 0;
	int diceroll = 0;
	int flag = 0;
	int[] item;
	// boolean check = true;

	// 쓰레드와 게임의 시작, 종료를 관리하기 위한 변수
	boolean running;
	private int count;

	public DiceGameBoard() {
		try {
			URL url = getClass().getResource("map.png");
			Image originalImage = ImageIO.read(url);

			map = originalImage.getScaledInstance(Constants.SCREEN_WIDTH,
					Constants.SCREEN_HEIGHT, Image.SCALE_SMOOTH);

			headImage = new Image[2];
			for (int i = 0; i < headImage.length; i++) {
				url = getClass().getResource("player" + i + ".png");
				originalImage = ImageIO.read(url);
				headImage[i] = originalImage.getScaledInstance(
						Constants.CELL_WIDTH, Constants.CELL_HEIGHT,
						Image.SCALE_SMOOTH);
			}

			dice = new Image[6];
			for (int i = 0; i < dice.length; i++) {
				url = getClass().getResource((i + 1) + ".png");
				originalImage = ImageIO.read(url);
				dice[i] = originalImage.getScaledInstance(Constants.CELL_WIDTH,
						Constants.CELL_HEIGHT, Image.SCALE_SMOOTH);
			}
			url = getClass().getResource("Item.png");
			originalImage = ImageIO.read(url);
			itemImage = originalImage.getScaledInstance(Constants.CELL_WIDTH,
					Constants.CELL_HEIGHT, Image.SCALE_SMOOTH);

		} catch (Exception ex) {
		}

		setBackground(Color.black);
		setDoubleBuffered(true);

		// 게임 객체 생성
		player = new int[2][2];
		item = new int[2];
		font = new Font("나눔고딕코딩", Font.BOLD, 20);
		// 키보드 이벤트 처리기 등록
		// addKeyListener(keyHandler);
		startGame();

	}

	private void startGame() {

		player[0][0] = 10;
		player[0][1] = 1;
		player[1][0] = 10;
		player[1][1] = 2;
		item[0] = 1;
		item[1] = 0;
		Thread thread = new Thread(this);
		thread.start();
		int count = 0;
	}

	// 화면의 갱신이 필요할 때 호출되는 메서드 -> 출력을 처리하는 메서드
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);

		Graphics2D g2d = (Graphics2D) g;

		Image image = null;
		image = map;
		g2d.drawImage(image, 0, 0, Constants.SCREEN_WIDTH,
				Constants.SCREEN_HEIGHT, this);

		for (int i = 0; i < headImage.length; i++) {
			g2d.drawImage(headImage[i], player[i][0] * Constants.CELL_WIDTH,
					player[i][1] * Constants.CELL_HEIGHT, Constants.CELL_WIDTH,
					Constants.CELL_HEIGHT, this);
		}

		g2d.drawImage(dice[diceroll], 840, 560, Constants.CELL_WIDTH,
				Constants.CELL_HEIGHT, this);

		g2d.drawImage(itemImage, item[0] * Constants.CELL_WIDTH, item[1]
				* Constants.CELL_HEIGHT, Constants.CELL_WIDTH,
				Constants.CELL_HEIGHT, this);

		g2d.setFont(new Font("SCORE" + count, Font.BOLD, 20));
		g2d.setFont(font);
		g2d.setColor(Color.gray);
		g2d.drawString("SCORE" + count, 840, 560);

		g2d.setFont(font);
		g2d.setColor(Color.ORANGE);
		if (flag == 0) {
			g2d.drawString("플레이어 턴", 840, 40);
		} else {
			g2d.drawString("컴퓨터 턴", 840, 40);
		}

		if (!running) {
			g2d.setFont(font);
			// as fontmetrics.getstringbounds : 지정된 폰트로 그려진 문자열의 영역 반환
			Rectangle2D r = g2d.getFontMetrics().getStringBounds("Game Over",
					g2d);
			g2d.setColor(Color.black);
			g2d.drawString("Game OVER",
					(Constants.SCREEN_WIDTH - (int) r.getWidth()) / 2,
					(Constants.SCREEN_HEIGHT - (int) r.getHeight()) / 2);
		}
	}

	/**
	 * frame 관리하는 쓰레드 메서드
	 */

	@Override
	public void run() {

		running = true;
		int computer = 0;
		while (running) {

			if (!running) {
				repaint();
			}
			diceroll++;
			if (diceroll > 5) {
				diceroll = 0;
			}
			if (number != 0) {
				if (flag == 0) {
					// check = false;
					movePaint(flag);
					moveEvent(flag);
					flag = 1;
					// check = true;
				} else if (flag == 1) {

					// check = false;
					movePaint(flag);
					moveEvent(flag);
					flag = 0;
					// check = true;
				}
			}

			// 컴퓨터 프로세스
			if (computer == 16) {
				if (flag == 1) {
					number = (int) ((Math.random() * 6) + 1);
				}
				computer = 0;
			}
			computer++;

			if (player[0][0] == 0 && player[0][1] == 9) {
				running = false;
			} else if (player[1][0] == 0 && player[1][1] == 9) {
				running = false;
			}
			// draw
			repaint();

			try {
				Thread.sleep(DELAY2);
			} catch (Exception ex) {
			}

		}
	}

	public void movePaint(int flag) {
		if (number != 0) {
			int number2 = number;
			// System.out.println("Ssss");
			for (int i = 0; i < number; i++) {
				if (player[flag][0] == 10
						&& (player[flag][1] == 1 || player[flag][1] == 2)) {
					player[flag][0] = 0;
					player[flag][1] = 0;
				} else if (player[flag][0] < 9 && player[flag][1] == 0) {
					player[flag][0]++;
				} else if (player[flag][0] == 9 && player[flag][1] == 0) {
					player[flag][1]++;
				} else if (player[flag][0] > 0 && player[flag][1] == 1) {
					player[flag][0]--;
				} else if (player[flag][0] == 0 && player[flag][1] == 1) {
					player[flag][1]++;
				} else if (player[flag][0] < 9 && player[flag][1] == 2) {
					player[flag][0]++;
				} else if (player[flag][0] == 9 && player[flag][1] == 2) {
					player[flag][1]++;
				} else if (player[flag][0] > 0 && player[flag][1] == 3) {
					player[flag][0]--;
				} else if (player[flag][0] == 0 && player[flag][1] == 3) {
					player[flag][1]++;
				} else if (player[flag][0] < 9 && player[flag][1] == 4) {
					player[flag][0]++;
				} else if (player[flag][0] == 9 && player[flag][1] == 4) {
					player[flag][1]++;
				} else if (player[flag][0] > 0 && player[flag][1] == 5) {
					player[flag][0]--;
				} else if (player[flag][0] == 0 && player[flag][1] == 5) {
					player[flag][1]++;
				} else if (player[flag][0] < 9 && player[flag][1] == 6) {
					player[flag][0]++;
				} else if (player[flag][0] == 9 && player[flag][1] == 6) {
					player[flag][1]++;
				} else if (player[flag][0] > 0 && player[flag][1] == 7) {
					player[flag][0]--;
				} else if (player[flag][0] == 0 && player[flag][1] == 7) {
					player[flag][1]++;
				} else if (player[flag][0] < 9 && player[flag][1] == 8) {
					player[flag][0]++;
				} else if (player[flag][0] == 9 && player[flag][1] == 8) {
					player[flag][1]++;
				} else if (player[flag][0] > 0 && player[flag][1] == 9) {
					player[flag][0]--;
				}/*
				 * else if (player[flag][0] == 0 && player[flag][1] == 9) {
				 * player[flag][1]++; }
				 */
				diceroll = number2 - 1;
				repaint();
				try {
					Thread.sleep(DELAY);
				} catch (Exception ex) {
				}
			}
			number = 0;
			// 아이템 충돌체크
			if (player[0][0] == item[0] && player[0][1] == item[1]) {
				// DELAY= (int)(DELAY-1);
				count = count + 10;
				item[0] = (int) (Math.random() * Constants.HORIZONTAL_COUNT);
				item[1] = (int) (Math.random() * Constants.VERTICAL_COUNT);
			}

		}

	}

	private void moveEvent(int flag) {

		
		// 사다리 이벤트
		if (player[flag][0] == 5 && player[flag][1] == 0) {
			player[flag][0] = 8;
			player[flag][1] = 4;
		} else if (player[flag][0] == 9 && player[flag][1] == 1) {
			player[flag][0] = 9;
			player[flag][1] = 2;
		} else if (player[flag][0] == 4 && player[flag][1] == 2) {
			player[flag][0] = 2;
			player[flag][1] = 7;
		} else if (player[flag][0] == 1 && player[flag][1] == 4) {
			player[flag][0] = 0;
			player[flag][1] = 5;
		} else if (player[flag][0] == 9 && player[flag][1] == 5) {
			player[flag][0] = 9;
			player[flag][1] = 8;
		} else if (player[flag][0] == 8 && player[flag][1] == 9) {
			player[flag][0] = 5;
			player[flag][1] = 9;
		}

		// 꼬리 이벤트
		if (player[flag][0] == 2 && player[flag][1] == 9) {
			player[flag][0] = 2;
			player[flag][1] = 1;
		} else if (player[flag][0] == 3 && player[flag][1] == 7) {
			player[flag][0] = 8;
			player[flag][1] = 1;
		} else if (player[flag][0] == 8 && player[flag][1] == 7) {
			player[flag][0] = 4;
			player[flag][1] = 3;
		}
	}

	private KeyAdapter keyHandler = new KeyAdapter() {

		@Override
		public void keyPressed(KeyEvent e) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_LEFT:
			case KeyEvent.VK_A:
				player[0][0]--;
				KeyEventCheck();
				break;
			case KeyEvent.VK_RIGHT:
			case KeyEvent.VK_D:
				player[0][0]++;
				KeyEventCheck();
				break;
			case KeyEvent.VK_UP:
			case KeyEvent.VK_W:
				player[0][1]--;
				KeyEventCheck();
				break;
			case KeyEvent.VK_DOWN:
			case KeyEvent.VK_S:
				player[0][1]++;
				KeyEventCheck();
				break;
			case KeyEvent.VK_SPACE:
				dice();
				KeyEventCheck();
				break;
			case KeyEvent.VK_F2:
				if (!running) {
					DELAY = 200;
					startGame();
					return;
				}
				break;
			case KeyEvent.VK_ESCAPE:
				// 게임종료
				String[] buttons = { "다시하기", "종료", "취소" };
				int result = JOptionPane.showOptionDialog(DiceGameBoard.this,
						"종료", "종료 하시겠습니까?", JOptionPane.YES_NO_CANCEL_OPTION,
						JOptionPane.QUESTION_MESSAGE, null, buttons, "취소");
				System.out.println(result);
				switch (result) {
				case 0:
					running = false;
					startGame();
					break;
				case 1:
					System.exit(0);
					break;
				default:
					break;
				}
			}
			super.keyPressed(e);
		}

		private void dice() {
			number = (int) ((Math.random() * 6) + 1);
			System.out.println(number);
		}
	};

	public void KeyEventCheck() {
		System.out.printf("%d, %d\n", player[0], player[1]);
		// 벽 충돌 체크
		if (player[0][0] < 0) { // 왼쪽 벽 충돌
			player[0][0] = 0;
		} else if (player[0][0] > Constants.HORIZONTAL_COUNT - 1) { // 오른쪽 충돌
			player[0][0] = Constants.HORIZONTAL_COUNT - 1;
		} else if (player[0][1] < 0) { // 위쪽 벽 충돌
			player[0][1] = 0;
		} else if (player[0][1] > Constants.VERTICAL_COUNT - 1) {// 아래쪽 충돌
			player[0][1] = Constants.VERTICAL_COUNT - 1;
		}
		repaint();
	}
}
